package com.coai.message.service

import com.coai.common.exception.ResourceNotFoundException
import com.coai.common.exception.ValidationException
import com.coai.message.dto.*
import com.coai.message.model.*
import com.coai.message.repository.*
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional

@Service
class ConversationService(
    private val conversationRepository: ConversationRepository,
    private val participantRepository: ConversationParticipantRepository,
    private val messageRepository: MessageRepository,
    private val messageService: MessageService
) {
    
    /**
     * 获取用户的所有会话列表
     */
    fun getUserConversations(userId: String): List<ConversationDto> {
        val conversations = conversationRepository.findByUserId(userId)
        
        return conversations.map { conversation ->
            val participants = participantRepository.findByConversationId(conversation.id!!)
            
            conversation.toDto(
                participants = participants,
                currentUserId = userId
            )
        }
    }
    
    /**
     * 创建会话
     */
    @Transactional
    fun createConversation(request: CreateConversationRequest, creatorId: String): ConversationDto {
        // 如果是单聊，检查是否已存在
        if (request.type == ConversationType.DIRECT) {
            if (request.participantIds.size != 1) {
                throw ValidationException("单聊只能有一个对方用户")
            }
            
            val otherUserId = request.participantIds.first()
            val existing = conversationRepository.findDirectConversation(
                creatorId, otherUserId, ConversationType.DIRECT
            )
            
            if (existing != null) {
                val participants = participantRepository.findByConversationId(existing.id!!)
                return existing.toDto(participants, creatorId)
            }
        }
        
        // 创建新会话
        val conversation = Conversation(
            type = request.type,
            name = request.name,
            avatar = request.avatar
        )
        
        val savedConversation = conversationRepository.save(conversation)
        
        // 添加创建者为参与者
        val creatorParticipant = ConversationParticipant(
            conversationId = savedConversation.id!!,
            userId = creatorId,
            role = if (request.type == ConversationType.GROUP) ParticipantRole.OWNER else ParticipantRole.MEMBER
        )
        participantRepository.save(creatorParticipant)
        
        // 添加其他参与者
        val otherParticipants = request.participantIds.map { userId ->
            ConversationParticipant(
                conversationId = savedConversation.id,
                userId = userId,
                role = ParticipantRole.MEMBER
            )
        }
        participantRepository.saveAll(otherParticipants)
        
        // 创建系统消息
        if (request.type == ConversationType.GROUP) {
            createSystemMessage(
                savedConversation.id,
                "${getUsername(creatorId)} 创建了群聊"
            )
        }
        
        val allParticipants = listOf(creatorParticipant) + otherParticipants
        return savedConversation.toDto(allParticipants, creatorId)
    }
    
    /**
     * 获取会话详情
     */
    fun getConversation(conversationId: String, userId: String): ConversationDto {
        val conversation = conversationRepository.findById(conversationId)
            .orElseThrow { ResourceNotFoundException("会话不存在") }
        
        // 验证用户是否在会话中
        if (!participantRepository.existsByConversationIdAndUserId(conversationId, userId)) {
            throw ValidationException("您不在该会话中")
        }
        
        val participants = participantRepository.findByConversationId(conversationId)
        
        return conversation.toDto(participants, userId)
    }
    
    /**
     * 更新会话信息（仅群聊）
     */
    @Transactional
    fun updateConversation(
        conversationId: String,
        request: UpdateConversationRequest,
        userId: String
    ): ConversationDto {
        val conversation = conversationRepository.findById(conversationId)
            .orElseThrow { ResourceNotFoundException("会话不存在") }
        
        if (conversation.type != ConversationType.GROUP) {
            throw ValidationException("单聊不支持修改名称")
        }
        
        // 检查权限（只有群主和管理员可以修改）
        val participant = participantRepository.findByConversationIdAndUserId(conversationId, userId)
            ?: throw ValidationException("您不在该会话中")
        
        if (participant.role !in listOf(ParticipantRole.OWNER, ParticipantRole.ADMIN)) {
            throw ValidationException("只有群主和管理员可以修改群信息")
        }
        
        // 更新会话信息
        val updated = conversation.copy(
            name = request.name ?: conversation.name,
            avatar = request.avatar ?: conversation.avatar
        )
        
        val saved = conversationRepository.save(updated)
        
        // 创建系统消息
        if (request.name != null && request.name != conversation.name) {
            createSystemMessage(
                conversationId,
                "${getUsername(userId)} 修改群名称为 \"${request.name}\""
            )
        }
        
        val participants = participantRepository.findByConversationId(conversationId)
        return saved.toDto(participants, userId)
    }
    
    /**
     * 添加成员（仅群聊）
     */
    @Transactional
    fun addParticipants(
        conversationId: String,
        request: AddParticipantsRequest,
        userId: String
    ): ConversationDto {
        val conversation = conversationRepository.findById(conversationId)
            .orElseThrow { ResourceNotFoundException("会话不存在") }
        
        if (conversation.type != ConversationType.GROUP) {
            throw ValidationException("单聊不支持添加成员")
        }
        
        // 验证权限
        if (!participantRepository.existsByConversationIdAndUserId(conversationId, userId)) {
            throw ValidationException("您不在该会话中")
        }
        
        // 添加新成员
        val newParticipants = request.userIds
            .filter { !participantRepository.existsByConversationIdAndUserId(conversationId, it) }
            .map { newUserId ->
                ConversationParticipant(
                    conversationId = conversationId,
                    userId = newUserId,
                    role = ParticipantRole.MEMBER
                )
            }
        
        if (newParticipants.isNotEmpty()) {
            participantRepository.saveAll(newParticipants)
            
            // 创建系统消息
            val usernames = newParticipants.joinToString(", ") { getUsername(it.userId) }
            createSystemMessage(
                conversationId,
                "${getUsername(userId)} 邀请 $usernames 加入群聊"
            )
        }
        
        val allParticipants = participantRepository.findByConversationId(conversationId)
        return conversation.toDto(allParticipants, userId)
    }
    
    /**
     * 移除成员（仅群聊）
     */
    @Transactional
    fun removeParticipant(
        conversationId: String,
        targetUserId: String,
        operatorId: String
    ): ConversationDto {
        val conversation = conversationRepository.findById(conversationId)
            .orElseThrow { ResourceNotFoundException("会话不存在") }
        
        if (conversation.type != ConversationType.GROUP) {
            throw ValidationException("单聊不支持移除成员")
        }
        
        // 检查操作者权限
        val operator = participantRepository.findByConversationIdAndUserId(conversationId, operatorId)
            ?: throw ValidationException("您不在该会话中")
        
        // 只有群主和管理员可以移除成员
        if (operator.role !in listOf(ParticipantRole.OWNER, ParticipantRole.ADMIN)) {
            throw ValidationException("只有群主和管理员可以移除成员")
        }
        
        // 不能移除群主
        val target = participantRepository.findByConversationIdAndUserId(conversationId, targetUserId)
            ?: throw ResourceNotFoundException("目标用户不在群聊中")
        
        if (target.role == ParticipantRole.OWNER) {
            throw ValidationException("不能移除群主")
        }
        
        // 移除成员
        participantRepository.deleteByConversationIdAndUserId(conversationId, targetUserId)
        
        // 创建系统消息
        createSystemMessage(
            conversationId,
            "${getUsername(operatorId)} 移除了 ${getUsername(targetUserId)}"
        )
        
        val participants = participantRepository.findByConversationId(conversationId)
        return conversation.toDto(participants, operatorId)
    }
    
    /**
     * 退出群聊
     */
    @Transactional
    fun leaveConversation(conversationId: String, userId: String) {
        val conversation = conversationRepository.findById(conversationId)
            .orElseThrow { ResourceNotFoundException("会话不存在") }
        
        if (conversation.type != ConversationType.GROUP) {
            throw ValidationException("单聊不支持退出")
        }
        
        val participant = participantRepository.findByConversationIdAndUserId(conversationId, userId)
            ?: throw ValidationException("您不在该会话中")
        
        // 群主不能直接退出，需要先转让群主
        if (participant.role == ParticipantRole.OWNER) {
            throw ValidationException("群主需要先转让群主身份才能退出")
        }
        
        // 移除参与者
        participantRepository.deleteByConversationIdAndUserId(conversationId, userId)
        
        // 创建系统消息
        createSystemMessage(conversationId, "${getUsername(userId)} 退出了群聊")
    }
    
    /**
     * 静音/取消静音会话
     */
    @Transactional
    fun toggleMute(conversationId: String, userId: String, muted: Boolean) {
        val participant = participantRepository.findByConversationIdAndUserId(conversationId, userId)
            ?: throw ValidationException("您不在该会话中")
        
        participant.muted = muted
        participantRepository.save(participant)
    }
    
    /**
     * 置顶/取消置顶会话
     */
    @Transactional
    fun togglePin(conversationId: String, userId: String, pinned: Boolean) {
        val participant = participantRepository.findByConversationIdAndUserId(conversationId, userId)
            ?: throw ValidationException("您不在该会话中")
        
        participant.pinned = pinned
        participantRepository.save(participant)
    }
    
    // 辅助方法
    
    private fun createSystemMessage(conversationId: String, content: String) {
        val systemMessage = Message(
            conversationId = conversationId,
            senderId = "system",
            messageType = MessageType.SYSTEM,
            content = content
        )
        messageRepository.save(systemMessage)
    }
    
    private fun getUsername(userId: String): String {
        // TODO: 从用户服务获取用户名
        return "用户$userId"
    }
    
    private fun Conversation.toDto(
        participants: List<ConversationParticipant>,
        currentUserId: String
    ): ConversationDto {
        val participantDtos = participants.map { it.toDto() }
        
        // 获取未读数
        val unreadCount = messageService.getUnreadCount(id!!, currentUserId).toInt()
        
        // 获取最后一条消息
        val lastMessageInfo = if (lastMessageId != null) {
            LastMessageInfo(
                id = lastMessageId!!,
                content = lastMessageContent ?: "",
                senderId = "unknown", // TODO: 从消息查询
                senderName = null,
                messageType = MessageType.TEXT,
                createdAt = lastMessageTime ?: createdAt!!
            )
        } else null
        
        return ConversationDto(
            id = id,
            type = type,
            name = name,
            avatar = avatar,
            lastMessage = lastMessageInfo,
            unreadCount = unreadCount,
            participants = participantDtos,
            createdAt = createdAt!!
        )
    }
    
    private fun ConversationParticipant.toDto(): ParticipantDto {
        return ParticipantDto(
            userId = userId,
            username = getUsername(userId),
            avatar = null, // TODO: 从用户服务获取
            role = role,
            muted = muted,
            pinned = pinned
        )
    }
}
